package cn.xiaobai.j2exe.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.xiaobai.j2exe.AbstractApplication;
import cn.xiaobai.j2exe.utils.FileUtils;
import cn.xiaobai.j2exe.utils.SourceUtils;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;

import java.io.File;
import java.net.URL;
import java.nio.file.Paths;
import java.util.*;

/**
 * app 配置
 *
 * @Author yangdaji
 * @Date 2023/12/26
 * @PackageName cn.xiaobai.j2exe.controller
 * @ClassName AppConfigController
 */
public class AppConfigController extends AbstractApplication {


//    @FXML
//    private Button select_jar_bt;

    @FXML
    private TextField jar_path_input;

    @FXML
    private TextField main_class_input;


    // add start
    @FXML
    private ListView<String> class_path_list;

    private ObservableList<String> classPathList = FXCollections.observableArrayList();

    @FXML
    private Button class_path_add_bt;

    @FXML
    private Button class_path_del_bt;

    // add end

    @FXML
    private ListView<String> remove_class_path_list;
    private ObservableList<String> removeClassPathList = FXCollections.observableArrayList();

    @FXML
    private Button remove_class_path_add_bt;

    @FXML
    private Button remove_class_path_del_bt;

    @FXML
    private AnchorPane app_conf;

    /**
     * 添加列表
     */
    private final Set<String> addItemValueSet = new HashSet<>(4);
    /**
     * 移除列表
     */
    private final Set<String> revmoeItemValueSet = new HashSet<>(4);

    private static String addItemValue;

    private static String delItemValue;


    public void main_class_input() {
        String mainClass = main_class_input.getText();
        globalConvertConfig.setMainClass(StrUtil.isNotBlank(mainClass) ? mainClass : null);
    }

    public void exe_jar_input() {
        String jarPath = jar_path_input.getText();
        if (StrUtil.isNotBlank(jarPath)) {
            File file = Paths.get(jarPath).toFile();
            if (FileUtil.isNotEmpty(file) && file.getName()
                    .endsWith(FileUtil.JAR_FILE_EXT)) {
                globalConvertConfig.setJarPath(file);
                globalConvertConfig.addClassPath(FileUtils.reversPath(file));

                verifyMainJar(file);
            }
        } else {
            globalConvertConfig.setJarPath(null);
        }
    }

    @FXML
    public void on_select_jar_click() {
        fileChooser.setTitle("选择执行的jar包");
        File file = fileChooser.showOpenDialog(app_conf.getScene().getWindow());
        if (FileUtil.isNotEmpty(file) && file.getName()
                .endsWith(FileUtil.JAR_FILE_EXT)) {
            String jarPath = FileUtils.reversPath(file);
            jar_path_input.setText(jarPath);
            globalConvertConfig.setJarPath(file);
            globalConvertConfig.addClassPath(FileUtils.reversPath(file));
            updateInitDir();

            // 验证jar包, 确保classpath 列表中首位存在
            verifyMainJar(file);
        }
    }


    private void verifyMainJar(File file) {
        String absolutePath = FileUtils.reversPath(file);
        if (CollectionUtil.isNotEmpty(classPathList)) {
            // 列表中存在,则直接提取到首位,否则添加到首位
            if (classPathList.contains(absolutePath)) {
                classPathList.removeIf(next -> absolutePath.equals(next));
            }
            classPathList.add(0, absolutePath);
        } else {
            classPathList.add(absolutePath);
        }
    }

    @FXML
    public void on_class_path_add_click(MouseEvent mouseEvent) {

        fileChooser.setTitle("选择一个依赖");
        File file = fileChooser.showOpenDialog(app_conf.getScene().getWindow());
        if (FileUtil.isEmpty(file)) {
            return;
        }

        String absolutePath = null;
        if (FileUtil.isNotEmpty(file)) {
            absolutePath = FileUtils.reversPath(file.getAbsolutePath());
        }

        // 获取鼠标点击源
        Object source = mouseEvent.getSource();
        if (source instanceof Button bt) {
            if (bt.equals(class_path_add_bt)) {
                // class-path add
                if (!addItemValueSet.contains(absolutePath) &&
                        !classPathList.contains(absolutePath)) {
                    addItemValueSet.add(absolutePath);
                    classPathList.addAll(addItemValueSet);
                    globalConvertConfig.addClassPath(addItemValueSet.toArray(new String[0]));

                    addItemValueSet.clear();
                }
            } else if (bt.equals(remove_class_path_add_bt)) {
                // remove-class-path add
                if (!revmoeItemValueSet.contains(absolutePath) &&
                        !removeClassPathList.contains(absolutePath)) {
                    revmoeItemValueSet.add(absolutePath);
                    removeClassPathList.addAll(revmoeItemValueSet);
                    globalConvertConfig.addRemoveLib(revmoeItemValueSet.toArray(new String[0]));

                    revmoeItemValueSet.clear();
                }
            }
        }
    }

    @FXML
    public void on_class_path_del_click(MouseEvent mouseEvent) {
        // 获取鼠标点击源
        Object source = mouseEvent.getSource();
        if (source instanceof Button bt) {
            if (bt.equals(class_path_del_bt)) {
                // class-path del
                if (addItemValue != null) {
                    globalConvertConfig.getClasspath()
                            .remove(addItemValue);
                    classPathList.remove(addItemValue);
                }
            } else if (bt.equals(remove_class_path_del_bt)) {
                // remove-path del
                if (delItemValue != null) {
                    globalConvertConfig.getRemovePlatformLibs()
                            .remove(delItemValue);
                    removeClassPathList.remove(delItemValue);
                }
            }
        }
    }

    @Override
    protected void refresh() {
        main_class_input.setText(globalConvertConfig.getMainClass());
        List<String> classpath = globalConvertConfig.getClasspath();
        if (CollectionUtil.isNotEmpty(classpath)) {
            String path = classpath.get(0);
            jar_path_input.setText(FileUtils.reversPath(path));
            globalConvertConfig.setJarPath(Paths.get(path).toFile());
            classPathList.clear();
            classPathList.addAll(classpath);
        }
        List<String> removePlatformLibs = globalConvertConfig.getRemovePlatformLibs();
        if (CollectionUtil.isNotEmpty(removePlatformLibs)) {
            removeClassPathList.clear();
            removeClassPathList.addAll(removePlatformLibs);
        }

    }

    @Override
    protected void updateInitDir() {
        File jarPath = globalConvertConfig.getJarPath();
        if (jarPath != null &&
                !Objects.equals(jarPath, fileChooser.getInitialDirectory())) {
            fileChooser.setInitialDirectory(jarPath.getParentFile());
        }

    }


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        addListener(this);

        initListener();
        initResource();

        refresh();
    }

    private void initListener() {

        class_path_list.setItems(classPathList);
        remove_class_path_list.setItems(removeClassPathList);
        // 监听器获取选择的值
        class_path_list.getSelectionModel().selectedItemProperty()
                .addListener((observable, oldValue, newValue) -> {
                    addItemValue = newValue;
                });

        remove_class_path_list.getSelectionModel().selectedItemProperty()
                .addListener((observable, oldValue, newValue) -> {
                    delItemValue = newValue;
                });

        main_class_input.focusedProperty()
                .addListener((observable, oldValue, newValue) -> main_class_input());

        jar_path_input.focusedProperty()
                .addListener((observable, oldValue, newValue) -> exe_jar_input());

    }

    private void initResource() {
        class_path_add_bt.setGraphic(new ImageView(SourceUtils.getPngImg("add-20.png")));
        class_path_del_bt.setGraphic(new ImageView(SourceUtils.getPngImg("del-20.png")));

        remove_class_path_add_bt.setGraphic(new ImageView(SourceUtils.getPngImg("add-20.png")));
        remove_class_path_del_bt.setGraphic(new ImageView(SourceUtils.getPngImg("del-20.png")));
    }
}
